package com.weijian.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.weijian.dal.entity.Course;
import com.weijian.dal.enums.CourseStatus;
import com.weijian.dal.mapper.CourseMapper;
import com.weijian.service.CourseService;
import com.weijian.util.RedisKeyUtil;
import jakarta.annotation.Resource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

/**
 * 课程服务实现类
 *
 * @author weijian
 * @since 2024-12-20
 */
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public IPage<Course> getCourseList(Integer page, Integer size) {
        // 参数验证和规范化
        if (page == null || page < 1) page = 1;
        if (size == null || size < 1) size = 10;
        if (size > 100) size = 100; // 限制最大页面大小

        // 只有满足缓存条件的请求才考虑使用缓存和存储缓存
        boolean isCacheable = page <= 5 && (size == 10 || size == 20 || size == 50);

        if (isCacheable) {
            // 构建缓存key
            String cacheKey = RedisKeyUtil.getCourseListKey(page, size);

            // 尝试从缓存中获取
            IPage<Course> cachedPage = (IPage<Course>) redisTemplate.opsForValue().get(cacheKey);
            if (cachedPage != null) {
                return cachedPage;
            }

            // 缓存未命中，查询数据库
            Page<Course> pageParam = new Page<>(page, size);
            LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Course::getStatus, CourseStatus.ONLINE.getCode())
                    .orderByDesc(Course::getCreateTime);

            IPage<Course> result = this.page(pageParam, wrapper);

            // 只有满足缓存条件的数据才存入缓存
            long expireTime = page <= 3 ? 15 : 10; // 前3页缓存15分钟，其他缓存10分钟
            redisTemplate.opsForValue().set(cacheKey, result, expireTime, TimeUnit.MINUTES);

            return result;
        } else {
            // 不满足缓存条件的请求直接查询数据库，不进行缓存
            Page<Course> pageParam = new Page<>(page, size);
            LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Course::getStatus, CourseStatus.ONLINE.getCode())
                    .orderByDesc(Course::getCreateTime);

            return this.page(pageParam, wrapper);
        }
    }


    @Override
    public Course getCourseDetail(Long id) {
        // 尝试从缓存中获取
        String cacheKey = RedisKeyUtil.getCourseDetailKey(id);
        Course cachedCourse = (Course) redisTemplate.opsForValue().get(cacheKey);

        if (cachedCourse != null) {
            return cachedCourse;
        }

        // 缓存未命中，查询数据库
        LambdaQueryWrapper<Course> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Course::getId, id)
                .eq(Course::getStatus, CourseStatus.ONLINE.getCode());

        Course result = this.getOne(wrapper);

        // 将结果存入缓存，设置过期时间30分钟
        redisTemplate.opsForValue().set(cacheKey, result, 30, TimeUnit.MINUTES);

        return result;
    }

    /**
     * 清除课程列表缓存
     */
    public void clearCourseListCache() {
        // 由于RedisTemplate没有直接支持通配符删除，这里简单处理几种常见情况
        // 实际项目中可能需要使用Redis的SCAN命令来查找匹配的键
        for (int page = 1; page <= 100; page++) {
            for (int size = 1; size <= 100; size++) {
                String key = RedisKeyUtil.getCourseListKey(page, size);
                redisTemplate.delete(key);
            }
        }
    }

    /**
     * 清除课程详情缓存
     *
     * @param id 课程ID
     */
    public void clearCourseDetailCache(Long id) {
        String key = RedisKeyUtil.getCourseDetailKey(id);
        redisTemplate.delete(key);
    }
}